home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-06-22 | 12.2 KB | 409 lines | [TEXT/CWIE] |
- #include "ConvertToFinderIconPict.h"
- #include "Finder.h"
- #include "MoreFilesExtras.h"
- #include <QDOffscreen.h>
- #include <Palettes.h>
- #include <QDOffscreen.h>
- #include <stdio.h>
-
-
- const short kCustomIconResID = -16455;
-
- CFinderIconPicture::CFinderIconPicture ( short vRefNum, long dirID ) :
- mVRefNum ( vRefNum ),
- mDirID ( dirID ),
- mPix ( nil )
- {
- }
-
- CFinderIconPicture::~CFinderIconPicture ( )
- {
- TearDownPixMap();
- }
-
- void CFinderIconPicture::AddCustomIconResource ( short refNum, OSType resType, GWorldPtr pic, Rect& r, unsigned short depth )
- { Handle h = MakeIcon ( pic, & r, depth, 32 );
-
- if ( h )
- AddResource ( h, resType, kCustomIconResID, "\p" );
- }
-
- void CFinderIconPicture::CreateIconResourcesToFile ( GWorldPtr pic, short refNum, Rect& r )
- {
- Handle iconPound = MakeICN_pound ( pic, pic, & r, 32 );
- AddResource ( iconPound, 'ICN#', kCustomIconResID, "\p" );
-
- AddCustomIconResource ( refNum, 'icl8', pic, r, 8 );
- // AddCustomIconResource ( refNum, 'icl4', pic, r, 4 );
- }
-
- static inline void PLstrcpy ( StringPtr dest, const StringPtr source )
- {
- BlockMoveData ( source, dest, source[0] + 1 );
- }
-
- static void UniqueXYFilename ( unsigned short x, unsigned short y, StringPtr str )
- { const unsigned char spaceChar = ' ';
- const unsigned char nonBreakingSpaceChar = 0x01;
-
- str[0] = 0;
-
- for ( short i = 14; i >= 0 ; i -- )
- str[ ++ str[0] ] = ( y & ( 1 << i ) ) ? spaceChar : nonBreakingSpaceChar;
-
- for ( short i = 14; i >= 0 ; i -- )
- str[ ++ str[0] ] = ( x & ( 1 << i ) ) ? spaceChar : nonBreakingSpaceChar;
-
- }
-
- void CFinderIconPicture::CreateTiledFile ( GWorldPtr pic, unsigned short x, unsigned short y )
- { FSSpec spec;
- Str255 fileName = "\pFile ";
-
- UniqueXYFilename ( x, y, fileName );
-
- if ( FSMakeFSSpec ( mVRefNum, mDirID, fileName, & spec ) == noErr )
- FSpDelete ( & spec );
-
- FSpCreateResFile ( & spec, 'VFol', 'VFI#', smRoman );
-
- FInfo fileInfo;
- if ( FSpGetFInfo ( & spec, & fileInfo ) == noErr )
- {
- fileInfo.fdLocation.h = x;
- fileInfo.fdLocation.v = y;
- fileInfo.fdFlags = kHasCustomIcon | kNameLocked | kHasBeenInited;
-
- FSpSetFInfo ( & spec, & fileInfo );
- }
-
- short refNum = FSpOpenResFile ( & spec, fsRdWrPerm );
- if ( refNum && ResError() == noErr )
- { Rect r;
-
- r.top = y;
- r.bottom = y + 32;
-
- r.left = x;
- r.right = x + 32;
-
- CreateIconResourcesToFile ( pic, refNum, r );
-
- CloseResFile ( refNum );
-
- }
- }
-
- void CFinderIconPicture::DeleteExistingIcons ( )
- {
- CInfoPBRec getCatInfoPB;
-
- getCatInfoPB.dirInfo.ioFDirIndex = 1; /* get first item */
-
- OSErr err = noErr;
- do
- { Str255 itemName = "\p";
-
- /* prepare to delete directory */
- getCatInfoPB.dirInfo.ioNamePtr = itemName;
- getCatInfoPB.dirInfo.ioVRefNum = mVRefNum;
- getCatInfoPB.dirInfo.ioDrDirID = mDirID; /* in this directory */
- OSErr err = PBGetCatInfoSync(&(getCatInfoPB));
- if ( err == noErr )
- {
- getCatInfoPB.dirInfo.ioFDirIndex ++;
-
- /* We have an item. Is it a file or directory? */
- if ( (getCatInfoPB.dirInfo.ioFlAttrib & ioDirMask) == 0 )
- {
- if ( getCatInfoPB.hFileInfo.ioFlFndrInfo.fdType == 'VFI#' && getCatInfoPB.hFileInfo.ioFlFndrInfo.fdCreator == 'VFol' )
- {
- err = PBHDeleteSync( (HParamBlockRec*) &(getCatInfoPB)); /* delete this item */
- if ( err == noErr )
- getCatInfoPB.dirInfo.ioFDirIndex --;
- }
-
- if ( err == fLckdErr )
- {
- (void) PBHRstFLockSync( (HParamBlockRec*) &(getCatInfoPB)); /* unlock it */
- err = PBHDeleteSync( (HParamBlockRec*) &(getCatInfoPB)); /* and try again */
- if ( err == noErr )
- getCatInfoPB.dirInfo.ioFDirIndex --;
- }
- }
- }
- } while ( err == noErr );
- }
-
- void CFinderIconPicture::AcceptPict ( GWorldPtr pic )
- {
- // "Tile" across the picture, creating icons for each file
- // DeleteDirectoryContents ( mVRefNum, mDirID, "\p" );
-
- // DeleteExistingIcons ();
-
- Rect gWorldRect = pic->portRect;
- for ( unsigned short y = gWorldRect.top; y < gWorldRect.bottom; y += 32 )
- {
- for ( unsigned short x = gWorldRect.left; x < gWorldRect.right; x += 32 )
- CreateTiledFile ( pic, x, y );
- }
- }
-
- Handle CFinderIconPicture::MakeICN_pound(GWorldPtr gwp, GWorldPtr maskP, Rect *srcRect, short iconDimension)
- /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- this returns a handle to the image data for an icon and it's mask, of size iconDimension x iconDimension.
- The icon is created by copying the srcRect of srcGWorld into a PixMap.
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
- { Handle icon;
- Handle iconMask;
- Size iconSize;
-
- icon = MakeIcon(gwp, srcRect,1,iconDimension);
-
- // Once we've made the icon, create a mask of the icon which has 1 bits
- // for every place 'inside' the enclosing rectangle.
- if(icon)
- { Handle iconMask = NewHandle ( GetHandleSize ( icon ) );
-
- for ( unsigned i = GetHandleSize ( iconMask ); i > 0; )
- (*iconMask)[--i] = 0xff;
-
- if(iconMask)
- {
- iconSize = GetHandleSize(icon);
- SetHandleSize(icon, iconSize + GetHandleSize(iconMask));
- // CheckError("\pSetHandleSize fail.",MemError());
- BlockMove(*iconMask, (Ptr)(((long)*icon) + iconSize), GetHandleSize(iconMask));
- DisposeHandle(iconMask);
- }
-
- }
-
- return icon;
- }
-
- Handle CFinderIconPicture::MakeIcon(GWorldPtr srcGWorld, Rect* srcRect, short dstDepth, short iconSize)
- /*
- Creates a handle to the image data for an icon, or nil if an error.
- The source image is specified by GWorld and regtangle defining the area
- to create the icon from.
- The type of icon is specified by the depth and Size paramters.
- iconSize is used for both height and width.
- For example, to create an Icl8 pass 8 for dstDepth and 32 for iconSize.
- to create an ics8 pass 8 for the dstDepth and 16 for iconSize.
- to create an ICON pass 1 for the dstDepth and 32 for iconSize.
-
-
- */
- {
- GWorldPtr saveWorld;
- GDHandle saveHandle;
- long bytesPerRow;
- long imageSize;
- Handle dstHandle;
- Rect iconFrame;
- QDErr err;
- Rect gWorldRect;
- Rect sourceRect = *srcRect;
-
- GetGWorld(&saveWorld,&saveHandle); // save Graphics env state
-
- SetGWorld(srcGWorld,nil);
-
- iconFrame.top = 0;
- iconFrame.left = 0;
- iconFrame.bottom = iconSize;
- iconFrame.right = iconSize;
-
- if ( mPix && ( ( (**mPix).pixelSize != dstDepth ) || ! EqualRect( & (**mPix).bounds, &iconFrame ) ) )
- TearDownPixMap();
-
- // make a gworld for the icl resource
- if ( ! mPix )
- {
- mPix = (PixMapHandle) NewHandleClear(sizeof(PixMap));
-
- /* See Tech Note #120 - for info on creating a PixMap by hand as SetUpPixMap
- does. SetUpPixMap was taken from that Tech Note....
- */
- // GWorldPtr destGWorld = nil;
- // err = NewGWorld ( & destGWorld, dstDepth, & iconFrame, GetCTable(dstDepth+200), nil, useTempMem );
-
- CTabHandle colorTableH = GetCTable(dstDepth);
- err = SetUpPixMap(dstDepth,&iconFrame,colorTableH, mPix);
- DisposeCTable ( colorTableH );
-
- if(err)
- return nil;
- }
-
- LockPixels( GetGWorldPixMap(srcGWorld) );
- LockPixels(mPix);
-
- gWorldRect = srcGWorld->portRect;
- if ( sourceRect.top < gWorldRect.top )
- {
- iconFrame.top = gWorldRect.top - sourceRect.top;
- sourceRect.top = gWorldRect.top;
- }
-
- if ( sourceRect.left < gWorldRect.left )
- {
- iconFrame.left = gWorldRect.left - sourceRect.left;
- sourceRect.left = gWorldRect.left;
- }
-
- if ( sourceRect.bottom > gWorldRect.bottom )
- {
- iconFrame.bottom = iconFrame.bottom - ( sourceRect.bottom - gWorldRect.bottom );
- sourceRect.bottom = gWorldRect.bottom;
- }
-
- if ( sourceRect.right > gWorldRect.right )
- {
- iconFrame.right = iconFrame.right - ( sourceRect.right - gWorldRect.right );
- sourceRect.right = gWorldRect.right;
- }
-
- CopyBits( (BitMap*) *srcGWorld->portPixMap, (BitMap*) *mPix,
- & sourceRect, &iconFrame, srcCopy | ( dstDepth > 4 ) ? ditherCopy : 0, nil);
-
- UnlockPixels(GetGWorldPixMap(srcGWorld));
-
- bytesPerRow = ((dstDepth * ((**mPix).bounds.right - (**mPix).bounds.left) + 31) / 32) * 4;
- imageSize = (bytesPerRow) * ((**mPix).bounds.bottom - (**mPix).bounds.top);
-
- SetZone ( ApplicationZone() );
- dstHandle = NewHandleClear(imageSize);
- err = MemError ();
- if(err || dstHandle == nil)
- {
- return nil;
- }
- HLock(dstHandle);
- BlockMove(GetPixBaseAddr(mPix),*dstHandle,imageSize);
- HUnlock(dstHandle);
- UnlockPixels(mPix);
-
- // TearDownPixMap(mPix);
-
- // Restore graphics env to previous state
- SetGWorld(saveWorld,saveHandle);
-
- HNoPurge(dstHandle);
-
- return dstHandle;
- }
-
-
- void CFinderIconPicture::TearDownPixMap()
- {
- if ( mPix )
- {
- // We really need to do more.... BUT It is the thought that counts..
- if ( (** mPix).pmTable )
- DisposeCTable ( (**mPix).pmTable );
- DisposePtr ( (**mPix).baseAddr );
-
- DisposeHandle( (Handle) mPix );
-
- mPix = nil;
- }
- }
-
- #define kDefaultRes 0x00480000 /* Default resolution is 72 DPI; Fixed type */
-
- OSErr CFinderIconPicture::SetUpPixMap(
- short depth, /* Desired number of bits/pixel in off-screen */
- Rect *bounds, /* Bounding rectangle of off-screen */
- CTabHandle colors, /* Color table to assign to off-screen */
- PixMapHandle aPixMap /* Handle to the PixMap being initialized */
- )
- {
- CTabHandle newColors; /* Color table used for the off-screen PixMap */
- Ptr offBaseAddr; /* Pointer to the off-screen pixel image */
- OSErr error; /* Returns error code */
- short bytesPerRow; /* Number of bytes per row in the PixMap */
-
-
- error = noErr;
- newColors = nil;
- offBaseAddr = nil;
-
- bytesPerRow = ((depth * (bounds->right - bounds->left) + 31) / 32) * 4;
-
- /* Clone the clut if indexed color; allocate a dummy clut if direct color*/
- if (depth <= 8)
- {
- newColors = colors;
- error = HandToHand((Handle *) &newColors);
- }
- else
- {
- newColors = (CTabHandle) NewHandle(sizeof(ColorTable) -
- sizeof(CSpecArray));
- error = MemError();
- }
- if (error == noErr)
- {
- /* Allocate pixel image; long integer multiplication avoids overflow */
- offBaseAddr = NewPtrClear((unsigned long) bytesPerRow * (bounds->bottom -
- bounds->top));
- if (offBaseAddr != nil)
- {
- /* Initialize fields common to indexed and direct PixMaps */
- (**aPixMap).baseAddr = offBaseAddr; /* Point to image */
- (**aPixMap).rowBytes = bytesPerRow | /* MSB set for PixMap */
- 0x8000;
- (**aPixMap).bounds = *bounds; /* Use given bounds */
- (**aPixMap).pmVersion = 0; /* No special stuff */
- (**aPixMap).packType = 0; /* Default PICT pack */
- (**aPixMap).packSize = 0; /* Always zero in mem */
- (**aPixMap).hRes = kDefaultRes; /* 72 DPI default res */
- (**aPixMap).vRes = kDefaultRes; /* 72 DPI default res */
- (**aPixMap).pixelSize = depth; /* Set # bits/pixel */
- (**aPixMap).planeBytes = 0; /* Not used */
- (**aPixMap).pmReserved = 0; /* Not used */
-
- /* Initialize fields specific to indexed and direct PixMaps */
- if (depth <= 8)
- {
- /* PixMap is indexed */
- (**aPixMap).pixelType = 0; /* Indicates indexed */
- (**aPixMap).cmpCount = 1; /* Have 1 component */
- (**aPixMap).cmpSize = depth; /* Component size=depth */
- (**aPixMap).pmTable = newColors; /* Handle to CLUT */
- }
- else
- {
- /* PixMap is direct */
- (**aPixMap).pixelType = RGBDirect; /* Indicates direct */
- (**aPixMap).cmpCount = 3; /* Have 3 components */
- if (depth == 16)
- (**aPixMap).cmpSize = 5; /* 5 bits/component */
- else
- (**aPixMap).cmpSize = 8; /* 8 bits/component */
- (**newColors).ctSeed = 3 * (**aPixMap).cmpSize;
- (**newColors).ctFlags = 0;
- (**newColors).ctSize = 0;
- (**aPixMap).pmTable = newColors;
- }
- }
- else
- error = MemError();
- }
- else
- newColors = nil;
-
- /* If no errors occured, return a handle to the new off-screen PixMap */
- if (error != noErr)
- {
- if (newColors != nil)
- DisposeCTable(newColors);
- }
-
- /* Return the error code */
- return error;
- }
-